(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('vue')) :
	typeof define === 'function' && define.amd ? define(['vue'], factory) :
	(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.JsonExcel = factory(global.vue));
})(this, (function (vue) { 'use strict';

	var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};

	function createCommonjsModule(fn, module) {
		return module = { exports: {} }, fn(module, module.exports), module.exports;
	}

	var download = createCommonjsModule(function (module, exports) {
	//download.js v4.2, by dandavis; 2008-2016. [MIT] see http://danml.com/download.html for tests/usage
	// v1 landed a FF+Chrome compat way of downloading strings to local un-named files, upgraded to use a hidden frame and optional mime
	// v2 added named files via a[download], msSaveBlob, IE (10+) support, and window.URL support for larger+faster saves than dataURLs
	// v3 added dataURL and Blob Input, bind-toggle arity, and legacy dataURL fallback was improved with force-download mime and base64 support. 3.1 improved safari handling.
	// v4 adds AMD/UMD, commonJS, and plain browser support
	// v4.1 adds url download capability via solo URL argument (same domain/CORS only)
	// v4.2 adds semantic variable names, long (over 2MB) dataURL support, and hidden by default temp anchors
	// https://github.com/rndme/download

	(function (root, factory) {
		{
			// Node. Does not work with strict CommonJS, but
			// only CommonJS-like environments that support module.exports,
			// like Node.
			module.exports = factory();
		}
	}(commonjsGlobal, function () {

		return function download(data, strFileName, strMimeType) {

			var self = window, // this script is only for browsers anyway...
				defaultMime = "application/octet-stream", // this default mime also triggers iframe downloads
				mimeType = strMimeType || defaultMime,
				payload = data,
				url = !strFileName && !strMimeType && payload,
				anchor = document.createElement("a"),
				toString = function(a){return String(a);},
				myBlob = (self.Blob || self.MozBlob || self.WebKitBlob || toString),
				fileName = strFileName || "download",
				blob,
				reader;
				myBlob= myBlob.call ? myBlob.bind(self) : Blob ;
		  
			if(String(this)==="true"){ //reverse arguments, allowing download.bind(true, "text/xml", "export.xml") to act as a callback
				payload=[payload, mimeType];
				mimeType=payload[0];
				payload=payload[1];
			}


			if(url && url.length< 2048){ // if no filename and no mime, assume a url was passed as the only argument
				fileName = url.split("/").pop().split("?")[0];
				anchor.href = url; // assign href prop to temp anchor
			  	if(anchor.href.indexOf(url) !== -1){ // if the browser determines that it's a potentially valid url path:
	        		var ajax=new XMLHttpRequest();
	        		ajax.open( "GET", url, true);
	        		ajax.responseType = 'blob';
	        		ajax.onload= function(e){ 
					  download(e.target.response, fileName, defaultMime);
					};
	        		setTimeout(function(){ ajax.send();}, 0); // allows setting custom ajax headers using the return:
				    return ajax;
				} // end if valid url?
			} // end if url?


			//go ahead and download dataURLs right away
			if(/^data:([\w+-]+\/[\w+.-]+)?[,;]/.test(payload)){
			
				if(payload.length > (1024*1024*1.999) && myBlob !== toString ){
					payload=dataUrlToBlob(payload);
					mimeType=payload.type || defaultMime;
				}else {			
					return navigator.msSaveBlob ?  // IE10 can't do a[download], only Blobs:
						navigator.msSaveBlob(dataUrlToBlob(payload), fileName) :
						saver(payload) ; // everyone else can save dataURLs un-processed
				}
				
			}else {//not data url, is it a string with special needs?
				if(/([\x80-\xff])/.test(payload)){			  
					var i=0, tempUiArr= new Uint8Array(payload.length), mx=tempUiArr.length;
					for(i;i<mx;++i) tempUiArr[i]= payload.charCodeAt(i);
				 	payload=new myBlob([tempUiArr], {type: mimeType});
				}		  
			}
			blob = payload instanceof myBlob ?
				payload :
				new myBlob([payload], {type: mimeType}) ;


			function dataUrlToBlob(strUrl) {
				var parts= strUrl.split(/[:;,]/),
				type= parts[1],
				decoder= parts[2] == "base64" ? atob : decodeURIComponent,
				binData= decoder( parts.pop() ),
				mx= binData.length,
				i= 0,
				uiArr= new Uint8Array(mx);

				for(i;i<mx;++i) uiArr[i]= binData.charCodeAt(i);

				return new myBlob([uiArr], {type: type});
			 }

			function saver(url, winMode){

				if ('download' in anchor) { //html5 A[download]
					anchor.href = url;
					anchor.setAttribute("download", fileName);
					anchor.className = "download-js-link";
					anchor.innerHTML = "downloading...";
					anchor.style.display = "none";
					document.body.appendChild(anchor);
					setTimeout(function() {
						anchor.click();
						document.body.removeChild(anchor);
						if(winMode===true){setTimeout(function(){ self.URL.revokeObjectURL(anchor.href);}, 250 );}
					}, 66);
					return true;
				}

				// handle non-a[download] safari as best we can:
				if(/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)) {
					if(/^data:/.test(url))	url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
					if(!window.open(url)){ // popup blocked, offer direct download:
						if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){ location.href=url; }
					}
					return true;
				}

				//do iframe dataURL download (old ch+FF):
				var f = document.createElement("iframe");
				document.body.appendChild(f);

				if(!winMode && /^data:/.test(url)){ // force a mime that will download:
					url="data:"+url.replace(/^data:([\w\/\-\+]+)/, defaultMime);
				}
				f.src=url;
				setTimeout(function(){ document.body.removeChild(f); }, 333);

			}//end saver




			if (navigator.msSaveBlob) { // IE10+ : (has Blob, but not a[download] or URL)
				return navigator.msSaveBlob(blob, fileName);
			}

			if(self.URL){ // simple fast and modern way using Blob and URL:
				saver(self.URL.createObjectURL(blob), true);
			}else {
				// handle non-Blob()+non-URL browsers:
				if(typeof blob === "string" || blob.constructor===toString ){
					try{
						return saver( "data:" +  mimeType   + ";base64,"  +  self.btoa(blob)  );
					}catch(y){
						return saver( "data:" +  mimeType   + "," + encodeURIComponent(blob)  );
					}
				}

				// Blob but not URL support:
				reader=new FileReader();
				reader.onload=function(e){
					saver(this.result);
				};
				reader.readAsDataURL(blob);
			}
			return true;
		}; /* end download() */
	}));
	});

	var script = {
	  name: 'vue3-json-excel',
	  props: {
	    // mime type [xls, csv]
	    type: {
	      type: String,
	      default: "xls",
	    },
	    // Json to download
	    jsonData: {
	      type: Array,
	      required: false,
	      default: null,
	    },
	    // fields inside the Json Object that you want to export
	    // if no given, all the properties in the Json are exported
	    fields: {
	      type: Object,
	      default: () => null,
	    },
	    // this prop is used to fix the problem with other components that use the
	    // variable fields, like vee-validate. exportFields works exactly like fields
	    exportFields: {
	      type: Object,
	      default: () => null,
	    },
	    // Use as fallback when the row has no field values
	    defaultValue: {
	      type: String,
	      required: false,
	      default: "",
	    },
	    // Title(s) for the data, could be a string or an array of strings (multiple titles)
	    header: {
	      default: '',
	    },
	    // Footer(s) for the data, could be a string or an array of strings (multiple footers)
	    footer: {
	      default: '',
	    },
	    // filename to export
	    name: {
	      type: String,
	      default: "jsonData.xls",
	    },
	    fetch: {
	      type: Function,
	    },
	    meta: {
	      type: Array,
	      default: () => [],
	    },
	    worksheet: {
	      type: String,
	      default: "表1",
	    },
	    //event before generate was called
	    beforeGenerate: {
	      type: Function,
	    },
	    //event before download pops up
	    beforeFinish: {
	      type: Function,
	    },
	    // Determine if CSV Data should be escaped
	    escapeCsv: {
	      type: Boolean,
	      default: true,
	    },
	    // long number stringify
	    stringifyLongNum: {
	      type: Boolean,
	      default: false,
	    },
	  },
	  setup(props) {
	    // props
	    const { type, fields, exportFields, 
	    beforeFinish, header, footer, 
	    stringifyLongNum, beforeGenerate, jsonData,
	    fetch, defaultValue, name, worksheet } =   vue.toRefs(props);

	    // computed
	    const idName = vue.computed(() => {
	      var now = new Date().getTime();
	      return "export_" + now;
	    });

	    const downloadFields = vue.computed(() => {
	      if (fields) return vue.toRaw(fields.value)
	      if(exportFields) return exportFields.value()
	    });

	    // methods
	    const export1 = async(data1, filename, mine) => {
	      let blob = base64ToBlob(data1, mine);
	      if (typeof beforeFinish === "function") await beforeFinish();
	      download(blob, filename, mine);
	    };

	    const base64ToBlob = (data1, mine) => {
	      let base64 = window.btoa(window.unescape(encodeURIComponent(data1)));
	      let bstr = atob(base64);
	      let n = bstr.length;
	      let u8arr = new Uint8ClampedArray(n);
	      while (n--) {
	        u8arr[n] = bstr.charCodeAt(n);
	      }
	      return new Blob([u8arr], { type: mine });
	    };

	    const jsonToXLS = (data1) => {
	      let xlsTemp =
	        '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><head><meta name=ProgId content=Excel.Sheet> <meta name=Generator content="Microsoft Excel 11"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>${worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--><style>br {mso-data-placement: same-cell;}</style></head><body><table>${table}</table></body></html>';
	      let xlsData = "<thead>";
	      const colspan = Object.keys(data1[0]).length;
	      //Header
	      if (header.value) {
	        xlsData += parseExtraData(
	          header.value,
	          '<tr><th colspan="' + colspan + '">${data}</th></tr>'
	        );
	      }
	      //Fields
	      xlsData += "<tr>";
	      for (let key in data1[0]) {
	        xlsData += "<th>" + key + "</th>";
	      }
	      xlsData += "</tr>";
	      xlsData += "</thead>";
	      //Data
	      xlsData += "<tbody>";
	      data1.map(function (item, index) {
	        xlsData += "<tr>";
	        for (let key in item) {
	          xlsData +=
	            "<td>" +
	            preprocessLongNum(
	              valueReformattedForMultilines(item[key])
	            ) +
	            "</td>";
	        }
	        xlsData += "</tr>";
	      });
	      xlsData += "</tbody>";
	      //Footer
	      if (footer.value) {
	        xlsData += "<tfoot>";
	        xlsData += parseExtraData(
	          footer.value,
	          '<tr><td colspan="' + colspan + '">${data}</td></tr>'
	        );
	        xlsData += "</tfoot>";
	      }
	      return xlsTemp
	        .replace("${table}", xlsData)
	        .replace("${worksheet}", worksheet.value);
	    };

	    const parseExtraData = (extraData, format) => {
	      let parseData = "";
	      if (Array.isArray(extraData)) {
	        for (var i = 0; i < extraData.length; i++) {
	          if (extraData[i])
	            parseData += format.replace("${data}", extraData[i]);
	        }
	      } else {
	        parseData += format.replace("${data}", extraData);
	      }
	      return parseData;
	    };

	    const preprocessLongNum = (value) => {
	      if (stringifyLongNum.value) {
	        if (String(value).startsWith("0x")) {
	          return value;
	        }
	        if (!isNaN(value) && value != "") {
	          if (value > 99999999999 || value < 0.0000000000001) {
	            return '="' + value + '"';
	          }
	        }
	      }
	      return value;
	    };

	    const valueReformattedForMultilines = (value) => {
	      if (typeof value == "string") return value.replace(/\n/gi, "<br/>");
	      else return value;
	    };

	    const getKeys = (data1, header1) => {
	      if (header1) {
	        return header1;
	      }
	      let keys = {};
	      for (let key in data1[0]) {
	        keys[key] = key;
	      }
	      return keys;
	    };

	    const parseValue = (value) => {
	      return value || value === 0 || typeof value === "boolean"
	        ? value
	        : defaultValue.value;
	    };

	    const getValueFromNestedItem = (item, indexes) => {
	      let nestedItem = item;
	      for (let index of indexes) {
	        if (nestedItem) nestedItem = nestedItem[index];
	      }
	      return parseValue(nestedItem);
	    };

	    const getValueFromCallback = (item, callback) => {
	      if (typeof callback !== "function") return defaultValue.value;
	      const value = callback(item);
	      return parseValue(value);
	    };

	    const getValue = (key, item) => {
	      const field = typeof key !== "object" ? key : key.field;
	      let indexes = typeof field !== "string" ? [] : field.split(".");
	      let value = defaultValue.value;
	      if (!field) value = item;
	      else if (indexes.length > 1)
	        value = getValueFromNestedItem(item, indexes);
	      else value = parseValue(item[field]);
	      if (key.hasOwnProperty("callback"))
	        value = getValueFromCallback(value, key.callback);
	      return value;
	    };

	    const getProcessedJson = (data1, header1) => {
	      let keys = getKeys(data1, header1).value;
	      let newData = [];
	      data1.map(function (item, index) {
	        let newItem = {};
	        for (let label in keys) {
	          let property = keys[label];
	          newItem[label] = getValue(property, item);
	        }
	        newData.push(newItem);
	      });
	      return newData;
	    };

	    const generate = async () => {
	      if (beforeGenerate && typeof beforeGenerate.value === "function") {
	        await beforeGenerate.value();
	      }
	      let data2 = jsonData && vue.toRaw(jsonData.value);
	      if ((fetch && typeof fetch.value === "function") || !jsonData) {
	        data2 = await fetch.value();
	      }
	      if(data2.length === 0) {
	        console.warn('无导出数据');
	        return 
	      }
	      const DATA = vue.toRaw(data2);
	      let json = getProcessedJson(DATA, downloadFields);
	      if (type.value === "html") {
	        // this is mainly for testing
	        return export1(
	          jsonToXLS(json),
	          name.value.replace(".xls", ".html"),
	          "text/html"
	        );
	      }
	      return export1(
	        jsonToXLS(json),
	        name.value,
	        "application/vnd.ms-excel"
	      );
	    };

	    return {
	      idName,
	      generate,
	      name
	    }
	  }
	};

	const _hoisted_1 = ["id"];

	function render(_ctx, _cache, $props, $setup, $data, $options) {
	  return (vue.openBlock(), vue.createElementBlock("span", {
	    id: $setup.idName,
	    onClick: _cache[0] || (_cache[0] = (...args) => ($setup.generate && $setup.generate(...args)))
	  }, [
	    vue.renderSlot(_ctx.$slots, "default", {}, () => [
	      vue.createTextVNode(" Download " + vue.toDisplayString($setup.name), 1 /* TEXT */)
	    ])
	  ], 8 /* PROPS */, _hoisted_1))
	}

	script.render = render;
	script.__file = "src/components/json-excel.vue";

	var version = "1.0.10-alpha";

	const VERSION  = version;
	// console.log('version:'+ VERSION);

	const install=(app)=>{
	  app.component(script.name, script );
	};

	var index = {
	  Vue3JsonExcel: script,
	  install
	};

	return index;

}));
